package fem2.element;

import inf.jlinalg.Array2DMatrix;
import inf.jlinalg.ArrayVector;
import inf.jlinalg.IMatrix;
import inf.jlinalg.IVector;

import java.util.ArrayList;

import org.junit.Test;

import fem2.Block;
import fem2.Debugger;
import fem2.Node;
import fem2.element.crack_sda.SeparationMode;

public class SeparationModeTest {

	@Test
	public void test1() {
		Node n1 = new Node(2.307341E02, 4.593297E02, 1.337819E02);
		Node n2 = new Node(2.87384E02, 5.355073E02, 1.32196E02);
		Node n3 = new Node(2.33101E02, 5.340271E02, 6.084163E01);
		Node n4 = new Node(1.752498E02, 5.045755E02, 1.017769E02);

		Block b = new Block(n1, n2, n3, n4);

		double elementVolume = b.computeVolume();
		Debugger.watch(elementVolume);

		IMatrix B = new Array2DMatrix(6, 12);

		new StructuralElement(b, null).computeB(b, B, 0.0, 0.0, 0.0);

		Debugger.watch("B = ", B);

		double nc1 = 0.13299195457811497;
		double nc2 = 0.9743163838933411;
		double nc3 = 0.1817160534859133;

		ArrayList<SeparationMode> validModes = new ArrayList<SeparationMode>();
		int[][] configurations = new int[][] { { 0 }, { 1 }, { 2 }, { 3 }, { 0, 1 }, { 0, 2 },
				{ 0, 3 } };
		int dim = 3;

		for (int i = 0; i < configurations.length; i++) {
			double gradx = 0, grady = 0, gradz = 0;
			for (int j = 0; j < configurations[i].length; j++) {
				gradx += B.get(0, configurations[i][j] * dim);
				grady += B.get(1, 1 + configurations[i][j] * dim);
				gradz += B.get(2, 2 + configurations[i][j] * dim);
			}
			double normgrad = Math.sqrt(gradx * gradx + grady * grady + gradz * gradz);
			gradx /= normgrad;
			grady /= normgrad;
			gradz /= normgrad;
			/*
			 * compute crack area
			 */
			double A = elementVolume * normgrad;
			/*
			 * check the separation mode
			 */
			SeparationMode mode = new SeparationMode(b, new ArrayVector(gradx, grady, gradz), A,
					configurations[i]);
			if (mode.validate()) {
				validModes.add(mode);
			}
		}

		Debugger.watch(validModes.size());

		SeparationMode bestMode = null;
		double cos = 0.0;
		Debugger.watch("++++++++++++++++++++++");
		for (SeparationMode mode : validModes) {
			IVector N = mode.getSeparationNormal();
			double tmp = N.get(0) * nc1 + N.get(1) * nc2 + N.get(2) * nc3;
			double sign = Math.signum(tmp);

			Debugger.watch("abs(tmp) = ", Math.abs(tmp));
			Debugger.watch("N = ", N);
			Debugger.watch("sign = ", sign);
			SeparationMode tempMode = new SeparationMode(b, new ArrayVector(nc1 * sign, nc2 * sign,
					nc3 * sign), mode.getCrackArea(), mode.getPositiveNodes());
			if (Math.abs(tmp) > Math.abs(cos) && tempMode.validate()) {
				cos = tmp;
				bestMode = mode;
			}
			Debugger.watch("----------------------------");
		}

		System.out.println(bestMode);
	}

	@Test
	public void test2() {
		Node n1 = new Node(4.126322E02, 5.238732E02, 1.422865E02);
		Node n2 = new Node(5.00000E02, 5.00000E02, 1.00000E02);
		Node n3 = new Node(4.165784E02, 5.50970E02, 2.00000E02);
		Node n4 = new Node(5.00000E02, 5.00000E02, 2.00000E02);

		Block b = new Block(n1, n2, n3, n4);

		double elementVolume = b.computeVolume();
		Debugger.watch(elementVolume);

		IMatrix B = new Array2DMatrix(6, 12);

		new StructuralElement(b, null).computeB(b, B, 0.0, 0.0, 0.0);

		Debugger.watch("B = ", B);

		double[] normal = new double[] { 5.117244E-01, -8.581321E-01, 4.180238E-02 };

		double A = 961.0287629726984;

		int[] posNodes = new int[] { 3 };

		SeparationMode mode = new SeparationMode(b, new ArrayVector(normal), A, posNodes);

		ArrayList<double[]> bound = mode.getCrackBoundaryByScanning();

		Debugger.watch("", bound);
	}
}
